【Java】Socket网络编程实现内网穿透、端口映射转发、内网穿透上网工具的编写,设置IP白名单防火墙 |
您所在的位置:网站首页 › java 数据转发 › 【Java】Socket网络编程实现内网穿透、端口映射转发、内网穿透上网工具的编写,设置IP白名单防火墙 |
这里写目录标题
简介更新
一、背景1.1 情景假设1.2 想要达到的目的1.3 局限1.3 解决方案一(路由器NAT)1.4 解决方案二(云服务器转发)
二、方案介绍2.1 方案简介2.2 具体流程2.3 编程要点2.4 关于web管理IP白名单的更新2.5 关于socks5代理穿透内网上网功能的更新
三、程序简介3.1 简介3.2 调试学习
四、上线使用4.1 测试使用4.2 设置自启动服务4.2.1 服务端开机自启动4.2.2 客户端开机自启动
4.3 IP白名单防火墙管理
简介
本篇博客将介绍内网穿透原理及方法,并将以代码的形式展现出来可靠且安全的内网穿透、端口映射转发工具 程序开源在我的GitHb仓库中,学习和使用了的麻烦给个Star啦,万分感谢 更新 更新了web管理,能够管理允许登录的IP,设置IP白名单防火墙更新了代理上网功能,能够代理内网,例如实现在校外访问校园内网才能访问的网站 一、背景 1.1 情景假设 假如我在学校里有一台台式电脑A,这台台式电脑在实验室局域网内拥有一个局域网IP 192.168.0.A(为了方便我们这样描述IP)我在家里有一台笔记本B,这台笔记本在家中局域网内拥有一个局域网IP192.168.0.B 1.2 想要达到的目的 我在家里想使用笔记本B通过ssh登录到A电脑的22号端口进行shell相关操作 1.3 局限 我们是没法直接访问到的,因为在当前网络环境下,我们使用的机子一般都不具备公网IP,这样我们在寻址时只靠对方的局域网IP是无法找到他的 1.3 解决方案一(路由器NAT) 我们的A机器是处于实验室的局域网内,但如果我们有权限去控制上层的网关路由器,即这个上层的路由器具有一个公网IP,假设为123.123.123.123,那么我们可以在路由器中设置端口映射(NAT),例如将路由器的10022端口映射到局域网内A电脑的22号端口,这样我们在家中只要通过IP+端口123.123.123.123:10022就可以登录到实验室里台式机A的22号ssh服务端口了但很多时候我们并没有权限去控制这样一个网关路由,因为在现在的网络环境下,很有可能我们整个一层楼甚至一栋楼使用一个公网IP,每个实验室里又一个路由器,存在路由器多级嵌套的情况,网关路由的操作权限不会那么轻易获取,并且即使获取也将出现每一层路由器都需要配置端口映射而十分繁琐 1.4 解决方案二(云服务器转发) 而换一种想法,如果我们拥有一台具有公网IP的云服务器,那么我们完全可以将云服务器作为一个中继,大家(A和B)都连接到这台具有公网IP的云服务器并保持连接,云服务器都记录好连接着的机器谁是谁,大家需要相互沟通时(B想连接A)就告诉云服务器我想和谁沟通并将想沟通的消息发送出去即可,这里可能解释的不清晰,我们后面将做进一步的详细介绍,后续的网络编程即是实现这样一个消息转发功能而最终达到端口映射。 二、方案介绍 2.1 方案简介必要条件,一台具有公网IP的云服务器 通过云服务器将访问传输的消息进行转发 假设我们的云服务器IP为101.101.101.101,我们将要编写一个服务端程序运行在云服务器上,并监听10101服务端口还需要编写一个客户端运行在实验室台式机上,该客户端需要登录并连接到服务端的10101号端口进行C/S信息交互如果我们想将云端的40022号端口映射到实验室台式机的22号端口,那么这对C/S程序最终将达到的目的是,当我们输入公网IP+端口101.101.101.101:40022时我们将能够直接与实验室内的192.168.0.A:22进行通信。 2.2 具体流程 服务端首先监听10101端口客户端建立与101.101.101.101:10101的TCP连接,这个连接Socket我们将之称为信息交互Socket服务端在10101端口接收到的连接Socket我们也称为信息交互Socket客户端将想要映射的端口通过信息交互Socket告知服务端,即告知服务端帮忙监听下云端的40022号端口服务端通过信息交互Socket得知需要对40022号端口进行监听当我在家中连接101.101.101.101:40022时,服务端将接收到连接请求并得到一个Socket,我们称之为SocketWan,随后将这个连接事件通过信息交互Socket告诉那个对应的客户端客户端在信息交互Socket上得知了这个连接事件,客户端程序发起一个到本机127.0.0.1:22的连接请求,这个连接将得到一个Socket,我们称之为SocketLan完成了所有的连接建立,后面就是进行SocketWan和SocketLan之间的消息转发了,这之间的消息均需要通过信息交互Socket进行间接转发,即①SocketWan得到的消息,一并通过信息交互Socket转发给客户端,客户端在信息交互Socket上了解到有来自SocketWan的消息,立即转发到对应的SocketLan上,这就实现从101.101.101.101:40022-->192.168.0.A:22的单向消息传输;②当SocketLan得到消息时,将其得到的消息通过信息交互Socket一并转发给服务端,服务端再将消息转发至对应的SocketWan上,这就实现从192.168.0.A:22-->101.101.101.101:40022的另一单向传输,最终就实现了两者的双向消息传输 2.3 编程要点 客户端需要读取配置文件,并登录至服务端,且携带想要映射的云端端口(类似云端40022端口)服务端监听服务端口10101,且需要处理客户端的登录事件,验证登录信息,并新开一个线程处理C/S的信息交互,并新开N个线程对需要监听的N个云端端口进行监听服务端需要处理新连接请求,即有用户连接到40022端口了,那么我们需要通知客户端你想要监听的40022号端口有了新连接客户端需要处理新连接事件,新建线程发起对本机或局域网内对应主机+端口的连接(例如本机127.0.0.1:22)客户端和服务端都将收到建立了连接的端口发来的应用层消息,我们需要对这些消息进行封装、形成格式规范的消息头+消息体,客户端和服务端通过信息交互Socket传递消息,接收方获取到转发事件对消息进行解析并转发到对应端口服务端和客户端都需要处理关闭连接请求消息传输时需要处理TCP粘包/拆包问题,需要规范我们的消息类型,对于登录事件、新连接事件、关闭连接事件、消息转发事件以及心跳检测事件等我们都需要有具体的消息格式规范服务端和客户端都需要处理异常断开情况,需进行心跳检测来判断是否发生了异常断开而未被捕捉产生的阻塞为达到安全使用的目的,对于服务端客户端的消息传输,防止被抓包获得我们的通信内容,我们需要对传输进行加密在登录时我们需要进行密码校验,以应对外部的攻击,例如恶意要求监听服务端1-65535所有端口注意资源的释放,关闭连接和异常断开时的线程资源释放,很多时候会出现难以发现的资源占用,可通过相关的命令(jstack jmap jhat)等查看进程线程的资源占用情况支持失败重试,当意外断网时,定期进行登录尝试 2.4 关于web管理IP白名单的更新使用springboot写了一个ip白名单防火墙管理网页,因为开放端口映射是比较危险的,公网上充斥着大量的攻击,可能内网机器由于映射到公网上受到攻击,因此我实现了一个IP管理的功能,在原有程序上增加了springboot框架,使用sqlite建立了一个表格,一般的linux系统都安装了sqlite3数据库引擎,没安装的可以百度如何安装,存储内容是, 字段备注ipip名称(主键),例如192.168.0.1addressIP的属地,精确至市create_time创建时间comment备注创建了web管理页面,登录页面认证后可添加需要放行的IP,该表外的IP将不被允许连接 2.5 关于socks5代理穿透内网上网功能的更新例如实现当你在家中的时候依然可以访问到校内图书馆网址,或者访问实验室内局域网内任意机子,即添加代理功能,客户端让云服务器监听7890端口,校外用户将系统代理设置为云服务器IP:7890就可以愉快使用内网了,实现的需要遵从socks5协议,不了解的可以参考Socks 5 协议解析,编写过程中学习了java编写的低配版,该实现是和我想达到的目的少了一层转发 三、程序简介 3.1 简介程序开源在我的GitHb仓库中,如果帮到了你麻烦点个star啦,万分感谢 项目是一个Maven工程,程序主要分为客户端相关、服务端相关以及公用的工具类,最新版本代码中添加了web和proxy包,分别实现web防火墙管理和socks5代理实现 客户端配置文件config_client.yaml common: server_addr: 127.0.0.1 # 云服务器地址 server_port: 10101 # 云服务器服务端口 与服务端配置一致 token: 123456 # 登录密码 与服务端配置一致 nat: ssh-2: type: tcp local_ip: 127.0.0.1 # 需要被映射的内网机器的IP local_port: 22 # 需要被映射的内网机器的端口 remote_port: 40022 # 对应的云端服务器映射端口 # 达到的效果是访问 server_addr+40022 相当于局域网内local_ip+local_port vnc-21: type: tcp local_ip: 127.0.0.1 local_port: 5901 remote_port: 45901 socks5_proxy: # 代理 将浏览器的代理或系统代理改为 socks5,server_addr:7999 实现代理学校内网上网 type: tcp remote_port: 7999 3.2 调试学习运行前需确保系统上有sqlite数据库引擎,一般的linux系统都默认安装了sqlite3数据库引擎,可直接命令行sqlite3查看是否正常弹出,没安装的可以百度如何安装 运行com.liang.server.Server.java,将会弹出如下(由于加了springboot管理,打印内容变了)![]() ![]() ![]() ![]() ![]() 上面的测试使用在终端断开后将停止运行,因此我们需要注册我们的服务,达到开机自启动,或者手动运行服务后终端掉线依然运行 4.2.1 服务端开机自启动执行vim /etc/systemd/system/natServer.service创建服务,编辑如下 [Unit] Description=nat server daemon After=syslog.target network.target Wants=network.target [Service] Type=simple User=name # 如果是root用户可省略 WorkingDirectory=/home/name/NatSoft # 编辑的时候一定要删除注释 这里更改为自己放置jar包和配置的绝对路径 ExecStart=/path/to/your/java -jar NatServer-v1.jar # 编辑的时候一定要删除注释 这里更改为自己在java命令的安装位置 可使用 which java查看 Restart= always RestartSec=1min [Install] WantedBy=multi-user.target执行如下 #启动natServer systemctl daemon-reload systemctl start natServer #设置为开机启动 systemctl enable natServer 4.2.2 客户端开机自启动执行sudo vim /etc/systemd/system/natClient.service创建服务,编辑如下 [Unit] Description=nat client daemon After=syslog.target network.target Wants=network.target [Service] Type=simple User=name # 编辑的时候一定要删除注释 这样可以使得进程归用户所有,使用jps查看时可以查看到,如果不设置,那么普通用户jps查看不到 WorkingDirectory=/home/name/NatSoft # 编辑的时候一定要删除注释 这里更改为自己放置jar包和配置文件的绝对路径 ExecStart=/path/to/your/java -jar NatClient-v1.jar # 编辑的时候一定要删除注释 这里更改为自己在java命令的安装位置 可使用 which java查看 Restart= always RestartSec=1min [Install] WantedBy=multi-user.target执行如下 #启动natServer systemctl daemon-reload systemctl start natClient #设置为开机启动 systemctl enable natClient 4.3 IP白名单防火墙管理 输入你设置的web管理端口,server_addr:10102![]() ![]() ![]() |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |